A New Toy reversing the different 'modes' of a target

by Swann
30 October 1998


red

Well, well, well... welcome back Swann! For those of you that don't know nothing, Swann is practically the FOUNDER of the whole +HCU Database. And if you give a look at aca100.htm you'll see why. This essay is both well written and well explained. Interesting for any reverser or protector. A little too much code maybe (you'll notice that this is IDA dumping) but the explanations make the effort of following it well worth. The two tools that are here targeted have some fairly easy protection schemes. You'll find and download an (uncracked) copy of the Customizer on my own tools.htm page. My copy is 226304 bytes long, apparently version 1.10 and has a ridicolous Cinderella type protection, so I guess it's not the same version that Swann encountered. Anyway, enjoy this good essay and enjoy both tools. You'll be able to see a very simple (and funny) use of customizer in my Scarecrow license agreements and how to defeat them, btw.

red
A New Toy

reversing the different 'modes' of a target 



by swann  30 October 1998



Level: intermediate

Tools: standard



Recently on one of those message boards, someone mentioned two tools

I had never heard of. The person and the context were somewhat obscure,

so I was a little reluctant checking them out. Eventually I did, however,

and methinks these tools are worth taking a look at. Their purpose is

runtime editing of Windows windows. Ever had a problem with greyed out

check-boxes? Well, these programs ungrey them so you can give them

the check mark they deserve. You can also send messages to windows,

and with Customiser-- yes, that's an "s", they're from Oz-- you can

even save the changes you've made at runtime (For this purpose,

Customiser leaves shortcuts in the application directory). I tried

these programs with warfare.exe, a cute little strategy game I

had cracked years ago with a lot of effort. With Magic Mouse, this

is just a blast. You select the window, choose "enable," click, and

it's enabled. It's so easy it almost takes the fun out of it.      

 



The programs in question are:



Magic Mouse Demo  mm32.exe  137728 bytes

Customiser Demo   cust.exe  215552 bytes



Magic Mouse is widely available as mm32demo.exe, Customiser seems to

be available only at the publisher Wanga International's website:

http://www.ozemail.com.au/~wanga

(Download was terribly slow).



Customiser is the more advanced program, it seems to contain all the

functionality of MagicMouse, plus the ability to save the changes. So

this is probably the one you want to get. It is also, from a reversing

point of view, less interesting, since the protection scheme is

trivial: a simple combination of time limit and a nag screen --

patching a "ret" in the beginning of the nag call takes care of both

-- and a limit to the amount of changes you an save, easily located

through string references. This is a five-minutes-crack and not in

need of further elaboration. So, in line with Frav's new policy, I

will not deal with this newer and more powerful tool, but with the

older one.



Magic Mouse, in addition to the nag-and time limit protection, also

has a feature-disabling restriction that is a little more challenging,

and an annoying switch from enabled to disabled at random intervals.



Let's take the obstacles in the order of occurrence. When I first

started the demo up, it was already expired. The usual suspect, the

call to getlocaltime cum subsequent check turns out to be guilty

again. 



     

00401DB5 E8 D6 2F 01 00		 call	 j__getdate

00401DBA 59			 pop	 ecx

00401DBB 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh

00401DC2 7F 2B			 jg	 short loc_401DEF

00401DC4 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh

00401DCB 75 09			 jnz	 short loc_401DD6

00401DCD 0F BE 4D FD		 movsx	 ecx, byte ptr [ebp-3]

00401DD1 83 F9 04		 cmp	 ecx, 4

00401DD4 7F 19			 jg	 short loc_401DEF  ;my problem was 							 ;here

00401DD6  loc_401DD6:		                           ; CODE XREF: .text:00401DCBj

00401DD6 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh

00401DDD 75 27			 jnz	 short loc_401E06

00401DDF 0F BE 45 FD		 movsx	 eax, byte ptr [ebp-3]

00401DE3 83 F8 04		 cmp	 eax, 4

00401DE6 75 1E			 jnz	 short loc_401E06

00401DE8 0F BE 55 FC		 movsx	 edx, byte ptr [ebp-4]

00401DEC 4A			 dec	 edx

00401DED 7E 17			 jle	 short loc_401E06





You make the appropriate changes, it's all fairly obvious. After this

modification, you're treated to the startup nagscreen, which also

turns up frequently during normal program execution. Breaking at

messageboxexa will take you to this beauty:





00401108			

00401108			 ;   S u b r o u t i n e

00401108			 ; Attributes: bp-based	frame

00401108			

00401108 sub_401108 proc near; CODE XREF: .text:00401DFCp

00401108 	         	       ; .text:00401E13p

00401108			       ; .text:00401E8Cp

00401108			

			

00401108			 push	 ebp

00401109 8B EC			 mov	 ebp, esp

0040110B 81 C4 2C FF FF	FF	 add	 esp, 0FFFFFF2Ch

00401111 53			 push	 ebx

00401112 56			 push	 esi

00401113 57			 push	 edi

00401114 8B 75 0C		 mov	 esi, [ebp+arg_4]

00401117 8B 5D 08		 mov	 ebx, [ebp+arg_0]

0040111A B8 E0 50 41 00		 mov	 eax, offset unk_4150E0

0040111F E8 AC 33 01 00		 call	 @__InitExceptBlockLDTC

00401124 33 D2			 xor	 edx, edx

00401126 89 15 CC 50 41	00	 mov	 dword_4150CC, edx

0040112C 6A 00			 push	 0

0040112E 53			 push	 ebx

0040112F E8 20 3A 01 00		 call	 j_EnableWindow

00401134 66 C7 85 3C FF	FF FF 14+mov	 [ebp+var_C4], 14h

0040113D 56			 push	 esi

0040113E 6A 00			 push	 0

00401140 8D 8D 50 FF FF	FF	 lea	 ecx, [ebp+var_B0]

00401146 51			 push	 ecx

00401147 E8 74 29 01 00		 call	 sub_413AC0

0040114C 83 C4 0C		 add	 esp, 0Ch

0040114F 8B F8			 mov	 edi, eax

00401151 83 85 48 FF FF	FF 04	 add	 [ebp+var_B8], 4

00401158 57			 push	 edi

00401159 8B 47 0C		 mov	 eax, [edi+0Ch]

0040115C FF 50 14		 call	 dword ptr [eax+14h]

0040115F 59			 pop	 ecx

00401160 8B F8			 mov	 edi, eax

00401162 83 AD 48 FF FF	FF 04	 sub	 [ebp+var_B8], 4

00401169 6A 02			 push	 2

0040116B 8D 95 50 FF FF	FF	 lea	 edx, [ebp+var_B0]

00401171 52			 push	 edx

00401172 E8 70 2A 01 00		 call	 sub_413BE7

00401177 83 C4 08		 add	 esp, 8

0040117A 66 C7 85 3C FF	FF FF 08+mov	 [ebp+var_C4], 8

00401183 4F			 dec	 edi

00401184 75 03			 jnz	 short loc_401189

00401186 4E			 dec	 esi

00401187 75 0C			 jnz	 short loc_401195

00401189			

00401189	 loc_401189:		       ; CODE XREF: sub_401108+7Cj

00401189 6A 00			 push	 0

0040118B 6A 00			 push	 0

0040118D 6A 10			 push	 10h

0040118F 53			 push	 ebx

00401190 E8 13 3A 01 00		 call	 j_PostMessageA

00401195			

00401195	 loc_401195:		       ; CODE XREF: sub_401108+7Fj

00401195 6A 01			 push	 1

00401197 53			 push	 ebx

00401198 E8 B7 39 01 00		 call	 j_EnableWindow

0040119D 8B 8D 2C FF FF	FF	 mov	 ecx, [ebp+var_D4]

004011A3 64 89 0D 00 00	00 00	 mov	 large fs:0, ecx

004011AA 5F			 pop	 edi

004011AB 5E			 pop	 esi

004011AC 5B			 pop	 ebx

004011AD 8B E5			 mov	 esp, ebp

004011AF 5D			 pop	 ebp

004011B0 C3			 retn	

004011B0			 sub_401108 endp

004011B0			

004011B1			





As you can see from the Xrefs, it's called from three different

locations. You can either cure this at the points of origin, or here

inside the call. No stack complications, just return without executing

-- should take care of this nagging problem.



Alright, now we're free to enjoy the pleasures of the program, only to

be interrupted by the program switching back from enabled to disabled

mode without asking us. Here we should be a bit careful, since we

don't want to patch away our own opportunity for disabling magic

mouse. We only want to get rid of the unmotivated switches executed by

the program without asking our permission. String references take you

to the neutral "call to switch,"

where it all comes together. It has "good" and "bad" callers. Stack

analysis shows that the good caller, i.e.: us, when we voluntarily

disable Magic Mouse, is 405a0a, while the bad, unvoluntary caller is

401e7a. This is the one we want to take care of. (The other callers

listed here by IDA didn't call while I monitored the program, they

might call later and you can then handle them accordingly).      





00401ECB			 ;   S u b r o u t i n e

00401ECB			 ; Attributes: bp-based	frame

00401ECB			

00401ECB sub_401ECB proc near	;BAD caller ; CODE XREF: .text:00401E7Ap

00401ECB 				       ; .text:00401EA5p

00401ECB				       ; sub_401F6A+4Ap

00401ECB				       ; .text:00401FE2p

00401ECB	                ;GOOD caller   ; .text:00405A0Ap

00401ECB				       ; .text:00405AB6p

00401ECB	     ; DATA XREF: .data:004152B8o

00401ECB		                       ; .data:004154B0o

00401ECB			

00401ECB			 arg_0=	dword ptr  8

00401ECB			

00401ECB			 push	 ebp

00401ECC 8B EC			 mov	 ebp, esp

00401ECE 53			 push	 ebx

00401ECF 8B 5D 08		 mov	 ebx, [ebp+arg_0]

00401ED2 83 7B 21 00		 cmp	 dword ptr [ebx+21h], 0

00401ED6 74 0F			 jz	 short loc_401EE7

00401ED8 6A 01			 push	 1

00401EDA 8D 43 21		 lea	 eax, [ebx+21h]

00401EDD 50			 push	 eax

00401EDE 53			 push	 ebx

00401EDF E8 93 1B 00 00		 call	 sub_403A77

00401EE4 83 C4 0C		 add	 esp, 0Ch

00401EE7			

00401EE7	 loc_401EE7:		       ; CODE XREF: sub_401ECB+Bj

00401EE7 33 D2			 xor	 edx, edx

00401EE9 89 53 21		 mov	 [ebx+21h], edx

00401EEC 80 7B 4B 00		 cmp	 byte ptr [ebx+4Bh], 0

00401EF0 74 0E			 jz	 short loc_401F00

00401EF2 C6 43 4D 00		 mov	 byte ptr [ebx+4Dh], 0

00401EF6 53			 push	 ebx

00401EF7 E8 41 47 00 00		 call	 sub_40663D  ;neutral switch call

00401EFC 59			 pop	 ecx

00401EFD 5B			 pop	 ebx

00401EFE 5D			 pop	 ebp

00401EFF C3			 retn	

00401F00			 ;





Further inspection of bad_caller shows this situation::





00401E64			       ;  bad_switch_caller

00401E64    loc_401E64:		       ; DATA XREF: .data:00415270o

00401E64 55			 push	 ebp

00401E65 8B EC			 mov	 ebp, esp

00401E67 8B 45 08		 mov	 eax, [ebp+8]

00401E6A 83 3D CC 50 41	00 0F	 cmp	 dword_4150CC, 0Fh

00401E71 7C 21			 jl	 short loc_401E94

00401E73 80 78 4B 00		 cmp	 byte ptr [eax+4Bh], 0

00401E77 74 07			 jz	 short loc_401E80;make unconditional

00401E79 50			 push	 eax

00401E7A E8 4C 00 00 00		 call	 sub_401ECB	;unmotivated switch

00401E7F 59			 pop	 ecx

00401E80			

00401E80 loc_401E80:		       ; CODE XREF: .text:00401E77j

00401E80 6A 00			 push	 0

00401E82 A1 F0 B9 41 00		 mov	 eax, dword_41B9F0

00401E87 8B 10			 mov	 edx, [eax]

00401E89 FF 72 0C		 push	 dword ptr [edx+0Ch]

00401E8C E8 77 F2 FF FF		 call	 sub_401108

00401E91 83 C4 08		 add	 esp, 8

00401E94			

00401E94 loc_401E94:		       ; CODE XREF: .text:00401E71j

00401E94 5D			 pop	 ebp

00401E95 C3			 retn	

00401E96			 ; 

  



So we want to avoid the unmotivated switch at 401e7a, and we do this

by reverting 401e77 into an unconditional jump.



Finally, time for peaceful inspection of the program. And time to take

a look at the most interesting part of the protection: the disabling

of the "exclude mode." The full version of Magic Mouse can exclude a

user defined set of windows, gathered in the file "exlude.lst." That

should help with the reduction of complexity and the focusing on

what's important. Let's see if we can find a way to reenable that.

When you try activating the exclude mode, you get a window telling you

that this feature is not available in the demo version. But we've been

lied to so many times, we're not quite ready yet to believe this. The

caller of this disappointing message is 40659b, and it's worth looking

at it -- and at its context, that's why the following listing is a

little longer than usual. 







004064CC	 loc_4064CC:		       ; DATA XREF: .data:004152D0o

004064CC 55				       ; .data:00415438o

004064CC			 push	 ebp

004064CD 8B EC			 mov	 ebp, esp

004064CF 51			 push	 ecx

004064D0 53			 push	 ebx

004064D1 8B 5D 08		 mov	 ebx, [ebp+8]

004064D4 33 C0			 xor	 eax, eax    ;0== NORMAL mode

004064D6 89 45 FC		 mov	 [ebp-4], eax

004064D9 8D 55 FC		 lea	 edx, [ebp-4]

004064DC 52			 push	 edx

004064DD 53			 push	 ebx

004064DE E8 C3 00 00 00		 call	 sub_4065A6

004064E3 83 C4 08		 add	 esp, 8

004064E6 80 7B 4B 00		 cmp	 byte ptr [ebx+4Bh], 0

004064EA 74 08			 jz	 short loc_4064F4

004064EC FF 73 19		 push	 dword ptr [ebx+19h]

004064EF E8 D2 E6 00 00		 call	 j_SetCursor

004064F4			

004064F4	 loc_4064F4:		       ; CODE XREF: .text:004064EAj

004064F4 5B			 pop	 ebx

004064F5 59			 pop	 ecx

004064F6 5D			 pop	 ebp

004064F7 C3			 retn	

004064F8			 ;


004064F8 004064F8 loc_4064F8: ; DATA XREF: .data:00415300o 004064F8 55 ; .data:00415450o 004064F8 push ebp 004064F9 8B EC mov ebp, esp 004064FB 51 push ecx 004064FC 53 push ebx 004064FD 8B 5D 08 mov ebx, [ebp+8] 00406500 C7 45 FC 02 00 00 00 mov dword ptr [ebp-4], 2; 2== MOVE mode 00406507 8D 45 FC lea eax, [ebp-4] 0040650A 50 push eax 0040650B 53 push ebx 0040650C E8 95 00 00 00 call sub_4065A6 00406511 83 C4 08 add esp, 8 00406514 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406518 74 08 jz short loc_406522 0040651A FF 73 19 push dword ptr [ebx+19h] 0040651D E8 A4 E6 00 00 call j_SetCursor 00406522 00406522 loc_406522: ; CODE XREF: .text:00406518j 00406522 5B pop ebx 00406523 59 pop ecx 00406524 5D pop ebp 00406525 C3 retn 00406526 ;
00406526 00406526 loc_406526: ; DATA XREF: .data:00415330o 00406526 55 ; .data:00415468o 00406526 push ebp 00406527 8B EC mov ebp, esp 00406529 51 push ecx 0040652A 53 push ebx 0040652B 8B 5D 08 mov ebx, [ebp+8] 0040652E C7 45 FC 04 00 00 00 mov dword ptr [ebp-4], 4; 4==SEND mode 00406535 8D 45 FC lea eax, [ebp-4] 00406538 50 push eax 00406539 53 push ebx 0040653A E8 67 00 00 00 call sub_4065A6 0040653F 83 C4 08 add esp, 8 00406542 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406546 74 08 jz short loc_406550 00406548 FF 73 19 push dword ptr [ebx+19h] 0040654B E8 76 E6 00 00 call j_SetCursor 00406550 00406550 loc_406550: ; CODE XREF: .text:00406546j 00406550 5B pop ebx 00406551 59 pop ecx 00406552 5D pop ebp 00406553 C3 retn 00406554 ;
00406554 00406554 loc_406554: ; DATA XREF: .data:00415318o 00406554 55 ; .data:00415480o 00406554 push ebp 00406555 8B EC mov ebp, esp 00406557 51 push ecx 00406558 53 push ebx 00406559 8B 5D 08 mov ebx, [ebp+8] 0040655C C7 45 FC 03 00 00 00 mov dword ptr [ebp-4],3 ;3=PREVIEW mode 00406563 8D 45 FC lea eax, [ebp-4]; we're gonna jump ; there later 00406566 50 push eax 00406567 53 push ebx 00406568 E8 39 00 00 00 call sub_4065A6 0040656D 83 C4 08 add esp, 8 00406570 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406574 74 08 jz short loc_40657E 00406576 FF 73 19 push dword ptr [ebx+19h] 00406579 E8 48 E6 00 00 call j_SetCursor 0040657E 0040657E loc_40657E: ; CODE XREF: .text:00406574j 0040657E 5B pop ebx 0040657F 59 pop ecx 00406580 5D pop ebp 00406581 C3 retn 00406582 ;
00406582 00406582 loc_406582: ; DATA XREF: .data:004152E8o 00406582 55 ; .data:00415498o 00406582 push ebp 00406583 8B EC mov ebp, esp 00406585 53 push ebx 00406586 8B 5D 08 mov ebx, [ebp+8] 00406589 53 push ebx 0040658A E8 FD FC FF FF call sub_40628C 0040658F 59 pop ecx 00406590 A1 F0 B9 41 00 mov eax, dword_41B9F0 00406595 8B 10 mov edx, [eax] 00406597 FF 72 0C push dword ptr [edx+0Ch] 0040659A 53 push ebx 0040659B E8 CA B9 FF FF call sub_401F6A; EXCLUDE mode doesn't ; work; 004065A0 83 C4 08 add esp, 8 004065A3 5B pop ebx 004065A4 5D pop ebp 004065A5 C3 retn 004065A6 What you can observe here are some strikingly similar pieces of code for the different "modes" you can work MagicMouse in. The first four sections are identical, except for the value that is being moved to [ebp-4]. Further inspection shows that it's 0 for the normal mode, 2 for move, 4 for send, and 3 for preview. It all comes together in location [41b9e4] which holds the code for the mode of operation. Obviously, the value that is conspicuously missing here is 1. And our last, failing, exclude mode section is the only one that has a different code -- leads us to the demo limit screen instead of the desired mode of operation. So I guess it couldn't hurt to try the code of the other sections with our missing value, especially since there are data references to the exclude mode. The only operational problem being that there isn't enough space in our section for the length of code in the other sections. So we'll have to be a little creative, but that should be worth it. We could, for instance, patch the first part of the code, up to the decisive line "mov dword ptr [ebp-4], 1" in our original location, and then jump to one of the other locations to finish the rest of the code which is identical in all sections. 00406582 ; activated EXCLUDE section 00406582 loc_406582: ; DATA XREF: .data:004152E8o 00406582 55 ; .data:00415498o 00406582 push ebp 00406583 8B EC mov ebp, esp 00406585 51 push ecx 00406586 53 push ebx 00406587 8B 5D 08 mov ebx, [ebp+8] 0040658A C7 45 FC 01 00 00 00 mov dword ptr [ebp-4], 1; "magic" value 00406591 EB D0 jmp short loc_406563; jmp to Preview-- 00406593 ; continue there
00406593 90 nop 00406594 90 nop And, what can I tell you, it works :) The program creates a file named "exclude.lst" in which it gathers all the windows you want to exclude from your operations. There are two restrictions remaining: the opportunity to specifically exclude hidden windows and system windows. I doubt that the code for these options is in the program. If it is, I couldn't locate it. But, of course, you can achieve the same effect with your exclude list. And you'll probably want to use the Customiser program anyway, instead of Magic Mouse, since its functionality is extended. And we're only in it for the reversing anyway.

redhomepage red links red anonymity +ORC redstudents' essays redacademy database redbots wars
redantismut redtools redcocktails redjavascript wars redsearch_forms redmail_fravia
redIs reverse engineering illegal?